/**
 * 站点分布
 *
 * @author hangzhou 
 */
import * as mars3d from "mars3d"
import { streetList, noiseList, deviceList } from "@mars/api/data/index"
import { renderTooltipContent } from "@mars/utils/renderTooltip"
import { isValidCoordinate } from "@mars/utils/mars-util"
import { ref } from "vue"
import MqttHandler from "@mars/utils/mqtt"
import showDetail from "./show-detail.vue"
import { marsPointTrans } from "@mars/widgets/basic/location-point/map"
import { isVisible } from "element-plus/es/utils"

const Cesium = mars3d.Cesium
const mqttClient = ref(null)
const sharedCheckData = ref(null)
export const eventTarget: mars3d.BaseClass = new mars3d.BaseClass()

let map: mars3d.Map // mars3d.Map三维地图对象
let graphicLayer: mars3d.layer.GraphicLayer // 矢量图层
// 距离阈值配置（单位：米）
const distanceThresholds = {
  close: 1000, // 近距离
  mid: 5000, // 中距离
  far: 50000 // 远距离
}
const stationList:any = ref([])
const showEntityData:any = ref([])
/**
 * 初始化地图业务，生命周期钩子函数（必须）
 * 框架在地图初始化完成后自动调用该函数
 * @param {mars3d.Map} mapInstance 地图对象
 * @returns {void} 无
 */
export async function onMounted(mapInstance: mars3d.Map): Promise<void> {
  map = mapInstance // 记录map
 

  // 创建Graphic图层
  graphicLayer = new mars3d.layer.GraphicLayer({
    name: "站点-地图点",
    pid: 99 // 图层管理 中使用，父节点id
  })
  map.addLayer(graphicLayer)

  initCameraView()
  // map.setCameraView({ lat: 31.531747, lng: 120.730147, alt: 17769.2, heading: 359.9, pitch: -55.5 })

  // graphicLayer.flyTo()
  graphicLayer.bindTooltip(
    (event: any) => {
      const item = event.graphic.attr
      // 当设备id有值时，才触发showDetail
      if (item.id) {
        return renderTooltipContent(item, showDetail)
      }
    },
    { 
      offsetX: 20,
      offsetY: -30,
      direction: "top",
      template: false // 禁用默认模板
    }
  )


  // 单击事件
  graphicLayer.on(mars3d.EventType.click, (event: any) => {
    const item = event.graphic.attr
    // 当设备id有值时，才触发openDetailsPannel
    if (item.id) {
      eventTarget.fire("openDetailsPannel", { item })
    }
  })

  await listStreet()
  await listNoise()
  await loadDeviceDataBatch()

  mqttClient.value = MqttHandler.getInstance((isConnected) => {
    console.log("Connection status:", isConnected)
  })

  // 初始化连接
  mqttClient.value.init(({ msg, topic }) => {
    // console.log(`Received message on ${topic}:`, msg)
    if (topic === "/device/data/post") {
      handleDeviceData(msg)
    }
  })

  mqttClient.value.subscribe(["/device/data/post"]) // , "/device/warning/post"
}

/**
 * 释放当前地图业务的生命周期函数
 * @returns {void} 无
 */
export function onUnmounted() {
  if (graphicLayer) {
    graphicLayer.clear()
    graphicLayer.remove()
  }
  eventTarget.off()
  mqttClient.value.end()
  map = null
}

export function initCameraView() {
  map.setCameraView({ lat: 31.531747, lng: 120.730147, alt: 17769.2, heading: 359.9, pitch: -55.5 })
}
/**
 * 获取街道list
 */
async function listStreet() {
  streetList().then((res:any) => {
    eventTarget.fire("loadStreetData", { data: res.data })
  })
}

async function listNoise() {
  noiseList().then((res:any) => {
    const arrData = res.data
    stationList.value = arrData
    eventTarget.fire("loadPointData", { data: arrData })
  })
}

function updateListNoise(arr: any) {
  const deviceMap = new Map<string, any>(
    arr.map(station => [station.deviceCode, station])
  )
  const arrData = stationList.value.map((item) => {
    const currentObj = deviceMap.get(item.deviceCode)
    return {
      ...item,
      leqRtd: currentObj?.leqRtd,
      colorCode: currentObj?.colorCode,
      monitoringTime: currentObj?.monitoringTime
    }
  })
  eventTarget.fire("loadPointData", { data: arrData })
}

// 配置常量
const BATCH_SIZE = 20 // 每批加载数量
const LOAD_DELAY = 100 // 批次间延迟(毫秒)

// 存储所有数据的变量
let allDeviceData: any[] = []
let currentBatchIndex = 0

// 批量加载设备
function loadDeviceDataBatch() {
  deviceList().then((res: any) => {

    allDeviceData = res.data

    currentBatchIndex = 0
    // 开始分批加载
    loadNextBatch()
  }).catch(error => {
    console.error("加载设备数据失败:", error)
  })
}

// 加载下一批数据
function loadNextBatch() {
  const batchStart = currentBatchIndex
  const batchEnd = Math.min(currentBatchIndex + BATCH_SIZE, allDeviceData.length)
  const batchData = allDeviceData.slice(batchStart, batchEnd)
  
  // 添加当前批次数据到地图
  addMapData(batchData)
  
  // 更新索引
  currentBatchIndex = batchEnd
  
  // 如果还有数据，继续加载下一批
  if (currentBatchIndex < allDeviceData.length) {
    setTimeout(loadNextBatch, LOAD_DELAY)
  } else {
    console.log("所有设备数据加载完成")
    // 所有数据加载完成后触发事件
    // eventTarget.fire("loadPointData", { data: allDeviceData });
  }
}


function addMapData(arr: any[], clearFlag = false) {
  // 清除现有图层
  if (currentBatchIndex === 0 || clearFlag) {
    graphicLayer.clear()
  }

  // 处理每个数据项
  arr.forEach(item => {
    const jd = Number(item.wgs84Longitude)
    const wd = Number(item.wgs84Latitude)

    // 验证坐标有效性
    if (!isValidCoordinate(jd, wd)) {
      console.warn("无效坐标", item)
      return
    }
    const position = Cesium.Cartesian3.fromDegrees(jd, wd)
    // 创建图元
    const graphic = createGraphic(item, position)

    // 添加到图层
    graphicLayer.addGraphic(graphic)
    
    // 添加标签
    addLabel(graphicLayer, position, item)
    
    // // 添加警告效果
    // if (item.laRtd > 60) {
    //   addWarningEffect(graphicLayer, position, graphic)
    // }
  })
}

// 处理监听的设备实时数据
function handleDeviceData(arr: any) {
  arr.forEach(item => {
    updateEntity(item.deviceCode, item)
  })
  updateListNoise(arr)
}

/**
 * 更新指定实体的属性值
 * @param entityId 实体唯一标识（需确保创建图元时已设置）
 * @param newProps 需要更新的新属性（包含坐标或其他业务字段）
 */
function updateEntity(entityId: string, newProps: Record<string, any>): void {
  // 1. 查找目标图元
  const targetGraphic:any = graphicLayer.getGraphicById(entityId)
  if (!targetGraphic) {
    // console.warn(`未找到ID为 ${entityId} 的实体`)
    return
  }
  try {
    // 3. 更新业务属性
    Object.assign(targetGraphic.options.attr, {
      leqRtd: newProps.leqRtd,
      warningFlag: newProps.warningFlag,
      colorCode: newProps.colorCode,
      monitoringTime: newProps.monitoringTime
    })
    targetGraphic.setStyle({
      image: getIconPath(targetGraphic.options.attr)
    })
    // 动态更新警告效果
    if ("warningFlag" in newProps) {
      const warningEffect = targetGraphic._warningEffect 
      if (newProps.warningFlag) {
        if (!warningEffect) {
          // 添加新警告效果
          addWarningEffect(graphicLayer, targetGraphic.position, targetGraphic)
        }
      } else {
        // 移除现有警告效果
        graphicLayer.removeGraphic(warningEffect)
        targetGraphic._warningEffect = undefined
      }
    }

    // 触发图层刷新
    graphicLayer.refreshCluster()
    
  } catch (error) {
    console.error(`更新实体 ${entityId} 失败:`, error)
  }
}
// 创建图层
function createGraphic(item: any, position: any) {

  return new mars3d.graphic.BillboardPrimitive({
    id: item.code,
    position,
    style: {
      image: getIconPath(item),
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      scaleByDistance: new Cesium.NearFarScalar(
        distanceThresholds.close, 1.0,
        distanceThresholds.far, 0.6
      ),
      visibleDepth: true,
      // 根据距离动态调整大小
      scale: computeDynamicScale(item.distance)
    },
    attr: item
  })
} 

export function showEntity(checkData:string[]) {
  sharedCheckData.value = checkData
  // console.log("============", allDeviceData)
  allDeviceData.forEach(item => {
    const targetGraphic: any = graphicLayer.getGraphicById(item.code)
    if (!targetGraphic) {
      // console.warn(`未找到ID为 ${item.code} 的实体`)
      return
    }
    // console.log("targetGraphic.options?.attr=====", targetGraphic.options?.attr)
    // 检查设备类型是否在允许列表中
    if (targetGraphic.options?.attr?.deviceTypeCode) {
      const deviceType = targetGraphic.options.attr.deviceTypeCode

      if (checkData.includes(deviceType)) {
        targetGraphic.show = true // 显示图形
        // console.log(`显示设备 ${deviceType}`)
      } else {
        targetGraphic.show = false // 隐藏图形
        // console.log(`隐藏设备 ${deviceType}`)
      }
    } else {
      console.warn("该实体没有 deviceCodeType 属性")
      targetGraphic.show = false // 默认隐藏
    }
    
    // 同时更新关联的label标签
    const shouldShow = checkData.includes(targetGraphic.options?.attr?.deviceTypeCode)
    if (targetGraphic._labelGraphic) {
      targetGraphic._labelGraphic.show = shouldShow
    }
    // 同时更新预警扫描效果
    if (targetGraphic._warningEffect) {
      targetGraphic._warningEffect.show = shouldShow
    }

    // 如果需要立即刷新视图
    graphicLayer.refreshCluster()
  })
}

// 获取图标路径
function getIconPath(item: any): string {
  let iconName = item.deviceTypeCode
  iconName += item.warningFlag ? "_red" : "_blue"
  return loadIcon(iconName, ".png")
}


// 根据距离计算动态缩放比例
function computeDynamicScale(distance: number): number {
  // if (distance < 1000) { return 0.8 }
  // if (distance > 15000) { return 1 }
  if (distance > 50000) { return 0.2 }
  return 1
}

// 添加预警扫描事件
function addWarningEffect(
  layer: any,
  position: any,
  parentGraphic: any,
  options?: {
    radius?: number;
    color?: any;
    duration?: number; // 效果持续时间(ms)，不传则永久存在
  }
): any {
  // 先移除旧效果（避免重复添加）
  if (parentGraphic && parentGraphic._warningEffect) {
    removeWarningEffect(parentGraphic, layer)
  }
  // 创建新效果
  const graphic = new mars3d.graphic.CirclePrimitive({
    position: position.clone(), // 避免引用问题
    style: {
      radius: options?.radius || 100,
      materialType: mars3d.MaterialType.CircleWave,
      materialOptions: {
        color: options?.color || new Cesium.Color(1.0, 0.0, 0.0, 1.0),
        speed: 10,
        count: 3
      },
      clampToGround: true,
      show: true
    }
  })

  // 添加到图层并建立引用
  layer.addGraphic(graphic)
  parentGraphic._warningEffect = graphic
  const shouldShow = sharedCheckData.value.includes(parentGraphic.options?.attr?.deviceTypeCode)
  parentGraphic._warningEffect.show = sharedCheckData.value.length === 0 ? true : shouldShow
  // graphic._parentEntity = parentGraphic // 双向绑定

  return graphic // 返回效果对象
}


// 移出预警效果
function removeWarningEffect(targetGraphic: any, layer: any) {
  if (!targetGraphic._warningEffect) { return }
  
  const effect = targetGraphic._warningEffect
  layer.removeGraphic(effect)
  
  targetGraphic._warningEffect = undefined
}


// 添加label事件 一个黑色面板，指向左下角黄色连线
function addLabel(layer, position, obj) {
  const graphic = new mars3d.graphic.DivGraphic({
    position,
    style: {
      html: `<div class="marsBlackPanel  animation-spaceInDown">
              <div class="marsBlackPanel-text">${obj.deviceName}</div>
          </div>`,
      horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
      verticalOrigin: Cesium.VerticalOrigin.CENTER,
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000), // 按视距距离显示
      clampToGround: true,
      // 高亮时的样式
      highlight: {
        // type: mars3d.EventType.click,
        className: "marsBlackPanel-highlight"
      }
    },
    show: true
  })
  // 将标签与主图形关联
  const mainGraphic = layer.getGraphicById(obj.code)
  if (mainGraphic) {
    mainGraphic._labelGraphic = graphic
  }

  layer.addGraphic(graphic)
}

export function showOrHideGraphic(text: string, callback: any) {
  graphicLayer.eachGraphic((graphic, i) => {
    const attr = graphic.attr ?? {}
    if ((attr?.JC && attr?.JC?.indexOf(text) !== -1) ||
      (attr?.NAME && attr?.NAME?.indexOf(text) !== -1) ||
      (attr?.DZ && attr?.DZ?.indexOf(text) !== -1)) {
      graphic.show = true
      callback && callback(attr, i)
    } else {
      graphic.show = false
    }
  })
}

export function flyToPoint(item:any) {
  graphicLayer.closeTooltip()

  const positions:any = {
    lng: item.x,
    lat: item.y
  }

  map.flyToPoint(positions, { radius: 2500 })
}


const loadIcon = (icon: string, iconSuffix: string) => {
  return new URL(`/src/assets/service/${icon}${iconSuffix}`, import.meta.url).href
}
